/*****************************
工程名称：直流有刷电机调速与换向控制
控制模式：
（1）PWM模式：0~100%占空比；频率1KHZ.
（2）POT航模电调模式：脉冲宽度：1~2ms;频率50HZ.
单片机工作频率：11.0592MHZ
单片机机器周期：1T模式
*****************************/
#include <reg52.h>

//sbit BDC_MODE=P3^5;//模式引脚，BDC_MODE=1:PWM模式。BDC_MODE=0：POT模式。
//bit BDC_MODE=1;//BDC_MODE=1:PWM模式。BDC_MODE=0：POT模式
bit KEY=1;
//sbit DR=P3^3;//PWM模式控制引脚
bit DR=1;
//sbit PWM_IN=P3^2;
//外部输入PWM输入引脚，也是外部中断引脚，通过边沿触发模式测量输入的脉宽(POT模式)或者占空比(PWM模式)
sbit PWM_OUT=P3^3;
//IN1单片机输出PWM信号控制电机转速，通过定时器0及其中断，输出占空比等于DC的PWM波
//sbit IN2=P3^0;//IN2通过高低电平控制正转反转

sfr AUXR=0X8E;//不可以位寻址的-定时器2
sfr INT_CLKO = 0x8f; //唤醒和时钟输出功能寄存器
sfr T2H = 0xD6; //定时器2高八位
sfr T2L = 0xD7;//定时器2低八位

int DC=0;//定义占空比的变量,赋初值
int time=1;
float WIDE_HIGH=0,WIDE_LOW=0,WIDE=0,DUTY=0;//WIDE_HIGH正周期，WIDE_LOW负周期，WIDE正周期或者负周期；
bit FLAGZHENG=1;//上次状态变量
bit FLAG=1;

//电机控制模式定义
typedef enum bdc_control_mode
{
	bdc_macon_mode=0,
	bdc_pwmcon_mode=1,
}BDC_CONTROL_MODE;
//电机控制模式结构体
typedef struct bdc_control_state
{
	BDC_CONTROL_MODE bdc_control_ways;
	void (*ctrlloop)(void);
	void (*ctrlint)(void);
}BDC_CONTROL_STATE;

typedef struct bdc_ctrlmode_checks
{
	BDC_CONTROL_MODE bdc_ctrlmode;
	bool (*ctrlcheck)(void);
	BDC_CONTROL_MODE new_bdc_ctrlmode;
}BDC_CONTROL_CHECK;

BDC_WORK_MODE  bdc_workmode_now=bdc_forward_mode;
BDC_WORK_MODE  bdc_workmode_old=bdc_backward_mode;

typedef enum
{
	true=1,
	false=0
}bool;

void timer0_ini()  //定时器0初始化函数
{
	AUXR |= 0x80;		//定时器0时钟1T模式
	TMOD &= 0xF0;		//设置定时器0模式-16位重装模式
	TL0 = 0x91;		//设置定时器0初值/重装值-低八位-10微妙定时
	TH0 = 0xFF;		//设置定时器0初值/重装值-高八位-10微妙定时
	EA=1;//开总中断
  ET0=1;//开定时器0中断
	TR0=1;//启动定时器0
}
void timer2_ini()  //定时器2初始化函数
{
	AUXR |= 0x04;  //定时器2设置为1T工作模式
	T2L = 0x00;		//设置定时器2初值-低八位
	T2H = 0x00;		//设置定时器2初值-低八位
}
void timer0() interrupt 1 //定时器0中断函数-用于输出占空比为DC的PWM波到P3.1 
{ 
	time++;
	if(time>100)
	{ 
		time=1;
	}
	if(1<=time && time<=DC)   //DC=占空比%
	{
		PWM_OUT=1;
	}
	if(DC<time && time<=100 )
	{
		PWM_OUT=0;
	}
}
void 	int0_ini() //中断0初始化函数
{
	EX0=1;//使能中断0
	IT0=0;//边沿触发模式
	EA=1;//开启中断
}
void INT0_int() interrupt 0
{
	bit FLAG;
	FLAG=INT0;//保存INT0的状态，1为上升沿，0为下降沿
	if (FLAGZHENG)//
	{
		if(FLAG)
			{
				AUXR &=~(1<<4);//定时器2停止计时
				T2H=0x00;//设置定时器2初值
				T2L=0x00;//设置定时器2初值
				AUXR |= 0x10; //定时器2开始计时
			}
			else 
			{
				AUXR &=~(1<<4);//定时器2停止计时
				WIDE_HIGH=(float)(T2L+T2H*256);//计算正周期	
				FLAGZHENG =!FLAGZHENG;	
				T2H=0x00;//设置定时器2初值
				T2L=0x00;//设置定时器2初值
				AUXR |= 0x10; //定时器2开始计时
			}
	}
	else 
		{
				AUXR &=~(1<<4);//定时器2停止计时
				WIDE_LOW=(float)(T2L+T2H*256);//计算负周期	
				FLAGZHENG =!FLAGZHENG;	
				T2H=0x00;//设置定时器2初值
				T2L=0x00;//设置定时器2初值
				AUXR |= 0x10; //定时器2开始计时
		}				
}


bool pwm_mode_check()//pwm模式
{
 if(KEY)
 {
   return true;
 }
 return false;
}
bool ma_mode_check()//航模模式
{
 if(!KEY)
 {
 return true;
 }
 return false;
}

//电机反转状态判断函数
bool bdc_reverse_check()
{
	switch bdc_ctrlmode_now
	case 0//航电模式
	{
		if(1.55<=WIDE_HIGH && WIDE_HIGH<=2)
		{	
		 return true;
		}
		return false;
	}
	case 1//PWM模式
	{
		if(DR==0)
		{	
		 return true;
		}
		return false;
	};
}
//电机正转状态判断函数
bool bdc_forward_check
{
switch bdc_ctrlmode_now
	case 0//航电模式
	{
		if(1<=WIDE_HIGH && WIDE_HIGH<1.45)
		{	
		 return true;
		}
		return false;
	}
	case 1//PWM模式
	{
		if(DR==1)
		{	
		 return true;
		}
		return false;
	}
}
//电机停转状态判断函数
bool bdc_stop_check
{
switch bdc_ctrlmode_now
	case 0//航电模式
	{
		if(1.45<=WIDE_HIGH && WIDE_HIGH<=1.55)
		{	
		 return true;
		}
		return false;
	}
	case 1//PWM模式
	{
		if(DC==0)
		{	
		 return true;
		}
		return false;
	}
}
void bdc_forward_perform
{
  switch bdc_ctrlmode_now
	case 0//航电模式
	{DC=(int)((1-(WIDE_HIGH-1)/0.45)*100);}
	case 1//PWM模式
	{DC=(int)(DUTY*100);}
  ET0=1;//开定时器0中断
//			IN2=1;//IN2/P3.0=1;
}
void bdc_forward_init
{}
void bdc_reverse_perform
{
	switch bdc_ctrlmode_now
	case 0//航电模式
	{DC=(int)(((WIDE_HIGH-1.55)/0.45)*100);}
	case 1//PWM模式
	{DC=(int)(DUTY*100);}
	ET0=1;//开定时器0中断
//IN2=1;//IN2/P3.0=1;
}
void bdc_reverse_init
{}
void bdc_stop_perform
{
	ET0=0;//关闭定时器0中断
//IN2=0;
	PWM_OUT=0;//IN1=0;
}
void bdc_stop_init
{}


void bdc_pwmcon_perform
{
	DUTY=WIDE_HIGH/(WIDE_HIGH+WIDE_LOW);
	workmode();
}
void bdc_pwmcon_init
{
	PX0=1;
	timer0_ini();
	timer2_ini();
  int0_ini();
}
void bdc_macon_perform
{
	WIDE_HIGH=WIDE_HIGH*9/100000	
	workmode();
}
void bdc_macon_init
{
	PX0=1;
	timer0_ini();
	timer2_ini();
  int0_ini();
}



//电机控制模式状态结构体：状态/执行函数/初始化函数
BDC_CONTROL_STATE bdc_control_mode[]=
{
	{bdc_pwmcon_mode,bdc_pwmcon_perform,bdc_pwmcon_init},
	{bdc_macon_mode,bdc_macon_perform,bdc_macon_init},
};
//电机控制模式状态检测结构体
BDC_CONTROL_CHECK bdc_ctrlmode_check[]=
{
	{bdc_pwmcon_mode,ma_mode_check,bdc_macon_mode},
	{bdc_macon_mode,pwm_mode_check,bdc_pwmcon_mode},
}
//电机工作模式
typedef enum bdc_work_mode
{
	bdc_forward_mode=0,
	bdc_reverse_mode,
	bdc_stop_mode,
}BDC_WORK_MODE;

typedef struct work_state
{
	BDC_WORK_MODE bdc_workmode,
	void (*ctrlloop)(void),
	void (*ctrlinit)(void),
}BDC_WORK_STATE;

typedef struct work_mode_check
{
	BDC_WORK_MODE bdc_workmode,
	bool (*ctrlcheck)(void),
	BDC_WORK_MODE new_bdc_workmode,
}BDC_WORK_CHECK;

BDC_WORK_STATE bdc_workmode_state[]=
{
	{bdc_forward_mode,bdc_forward_perform,bdc_forward_init},
	{bdc_reverse_mode,bdc_reverse_perform,bdc_reverse_init},
	{bdc_stop_mode,bdc_stop_perform,bdc_stop_init},
};

BDC_WORK_CHECK bdc_workmode_check[]=
{
	{bdc_forward_mode,bdc_reverse_check,bdc_reverse_mode},
	{bdc_forward_mode,bdc_stop_check,bdc_stop_mode},
	{bdc_reverse_mode,bdc_forward_check,bdc_forward_mode},
	{bdc_reverse_mode,bdc_stop_check,bdc_stop_mode},
	{bdc_stop_mode,bdc_forward_check,bdc_forward_mode},
	{bdc_stop_mode,bdc_reverse_check,bdc_reverse_mode},
};






void bdc_workmode_check_perform()
{
	for i=1:6
	{
		if (bdc_workmode_now==bdc_workmode_check[].bdc_workmode)
		{
			if (bdc_workmode[].ctrlcheck==ture)
			{
			 bdc_workmode_now=bdc_workmode[].new_bdc_workmode;
			 break;
			}
		}
  }
}
void workmode()
{
	for i=1:2
	{
	 if (bdc_workmode_now==bdc_workmode_state[i].bdc_workmode)
		 if(bdc_workmode_old!=bdc_workmode_now)
		 { 
			 bdc_workmode_old=bdc_workmode_now;
			 bdc_workmode_state[i].ctrlinit();
		 }
		 bdc_workmode_state[i].ctrlloop();
		 bdc_workmode_check_perform;
	}
}






















BDC_CONTROL_MODE  bdc_ctrlmode_now=bdc_pwmcon_mode;
BDC_CONTROL_MODE  bdc_ctrlmode_old=bdc_macon_mode;

//BDC电机控制模式函数
void bdc_mode_check_perform()
{
	for i=1:2
	{
		if (bdc_ctrlmode_now==bdc_ctrlmode_check[].bdc_ctrlmode)
		{
			if (bdc_ctrlmode_check[].ctrlcheck==ture)
			{
			 bdc_ctrlmode_now=bdc_control_way[].new_bdc_ctrlmode;
			 break;
			}
		}
  }
}



//主函数
void main()
{
	for i=1:2
	{
	 if (bdc_mode==bdc_control_mode[i].bdc_control_ways)
		 if(bdc_mode_old!=bdc_mode)
		 { 
			 bdc_mode_old=bdc_mode;
			 bdc_control_mode[i].ctrlint();
		 }
		 bdc_ctrlmode_state[i].ctrlloop();
		 bdc_ctrlmode_check_perform;
	}
}






















































void PWM_MODE() //MODE=1,PWM模式
{
	while(1)
	{
		if(FLAG != Flag_old)
		{
			WIDE_CALCU();
			FLAG = Flag_old;
		}
		DC=(int)(DUTY*100);	
		if (!DC) //占空比为0，停转：IN1=0，IN2=0;
		{	
			ET0=0;//关闭定时器0中断
//			IN2=0;
		  PWM_OUT=0;//IN1=0;
		}	
		if (!DR)//DR=0低电平反转：PWM_OUT=P3^1，IN1/P3.1/PWM_OUT, IN2/P3.0=1;
		{
				ET0=1;//打开定时器0中断
//			IN2=1;//IN2/P3.0=1;
		}
		if (DR) //DR=1高电平正转，IN1/P3.1=PWM_OUT, IN2/P3.2=0
		{
			ET0=1;//打开定时器0中断
//		IN2=0;//IN2/P3.0=0;
	  }		
	}
}
void POT_MODE() //MODE=0,POT模式
{
	while(1)
	{
		if(FLAG != Flag_old)
		{
			WIDE_CALCU();
			if(1<=WIDE_HIGH && WIDE_HIGH<1.45)	//脉宽1~1.45ms,电机正转：IN1/P3.1/PWM_OUT, IN2/P3.2=0		
			{
				DC=(int)((1-(WIDE_HIGH-1)/0.45)*100);
				ET0=1;//开定时器0中断
//			IN2=0;//IN2/P3.0=0;
			}
			if(1.55<=WIDE_HIGH && WIDE_HIGH<=2)//脉宽1.55~2ms,电机反转：IN1/P3.1/PWM_OUT, IN2/P3.0=1		
			{
				DC=(int)(((WIDE_HIGH-1.55)/0.45)*100);
				ET0=1;//开定时器0中断
//			IN2=1;//IN2/P3.0=1;
			}
			if(1.45<=WIDE_HIGH && WIDE_HIGH<=1.55)	//停转：IN1=0，IN2=0;
			{	
				ET0=0;//关闭定时器0中断
//		  IN2=0;
				PWM_OUT=0;//IN1=0;
			}
		FLAG = !Flag_old;
	  }
	}
}
void main()
{
	PX0=1;
	timer0_ini();
	timer2_ini();
  int0_ini();
	if(BDC_MODE)
	{
   PWM_MODE();
	}
	else
	{
	 POT_MODE();
	}
}